package com.keray.web.push.config;

import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpUtil;
import lombok.extern.slf4j.Slf4j;
import org.bson.types.ObjectId;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.event.ApplicationStartedEvent;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.event.ContextClosedEvent;
import org.springframework.context.event.EventListener;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.scheduling.annotation.Scheduled;

import javax.annotation.Resource;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.util.Enumeration;
import java.util.List;

import static org.springframework.data.mongodb.core.query.Criteria.where;
import static org.springframework.data.mongodb.core.query.Query.query;

/**
 * @author by keray
 * date:2021/7/26 4:05 下午
 */
@Configuration
@Slf4j
public class NameService {

    @Value("${server.port}")
    private Integer port;

    @Value("${spring.profiles.active}")
    private String active;

    private String serviceId;

    @Resource
    private MongoTemplate template;

    @EventListener
    public void started(ApplicationEvent applicationEvent) {
        if (applicationEvent instanceof ApplicationStartedEvent) {
            System.out.println("nameService start");
            NameServiceModel model = owner();
            serviceId = template.insert(model).getId();
        } else if (applicationEvent instanceof ContextClosedEvent) {
            System.out.println("nameService close.serviceId=" + serviceId);
            template.remove(query(where("_id").is(new ObjectId(serviceId))), NameServiceModel.class);

        }
    }

    public List<NameServiceModel> allClient() {
        return template.query(NameServiceModel.class).matching(query(where("active").is(active))).all();
    }

    @Scheduled(cron = "0 0/10 * * * ? ")
    public void heart() {
        for (var v : allClient()) {
            if (v.getId().equals(serviceId)) continue;
            try {
                if (!"OK".equals(HttpUtil.get(StrUtil.format("http://{}:{}/web-push/check-health", v.getIp(), v.getPort()), 2000))) {
                    log.warn("移除失效的服务：{}:{}", v.getIp(), v.getPort());
                    template.remove(query(where("_id").is(new ObjectId(v.getId()))), NameServiceModel.class);
                }
            } catch (Exception e) {
                log.warn("移除失效的服务：{}:{}", v.getIp(), v.getPort());
                template.remove(query(where("_id").is(new ObjectId(v.getId()))), NameServiceModel.class);
            }
        }
    }

    @Scheduled(cron = "0 0/9 * * * ? ")
    public void sub() {
        var owner = owner();
        var query = query(where("_id").is(new ObjectId(serviceId)));
        var k = template.findOne(query, NameServiceModel.class);
        if (k == null) {
            serviceId = template.insert(owner).getId();
        }
    }

    public NameServiceModel owner() {
        String ip = hostIp();
        return NameServiceModel.builder()
                .ip(ip)
                .port(port)
                .active(active)
                .build();
    }

    public String hostIp() {
        try {
            Enumeration<NetworkInterface> allNetInterfaces = NetworkInterface.getNetworkInterfaces();
            InetAddress ip;
            while (allNetInterfaces.hasMoreElements()) {
                NetworkInterface netInterface = allNetInterfaces.nextElement();
                Enumeration<InetAddress> addresses = netInterface.getInetAddresses();
                while (addresses.hasMoreElements()) {
                    ip = addresses.nextElement();
                    String retIp = ip.getHostAddress();
                    if (retIp.matches("192\\.168.*")) {
                        return retIp;
                    }
                    if (retIp.matches("10\\..*")) {
                        return retIp;
                    }
                    if (retIp.matches("172\\.16\\..*")) {
                        return retIp;
                    }
                }
            }
            return "";
        } catch (Exception e) {
            return "";
        }
    }

    public static void main(String[] args) {
        System.out.println(HttpUtil.get("http://vers7.cswx.com/api/vers7/check-health"));
    }
}
